var express = require("express");
var router = express.Router();

const {
    Cate,
    Article
} = require('../models')
const {
    Op
} = require('sequelize')

// 导入验证表单数据的中间件
const expressJoi = require('@escook/express-joi')

// 导入验证规则
const {
    news_add_schema
} = require('../schema/newsValidate')

const moment = require('moment')


// 导入解析 formdata 格式表单数据的包
const multer = require('multer')

// 导入处理路径的核心模块
const path = require('path')
const fs = require('fs');
const {
    resourceLimits
} = require("worker_threads");

// 新闻添加----表单
router.get('/news/add', async(req, res) => {
    // 获取分类数据
    const cates = await Cate.findAll({
        attributes: ['id', 'cate_name']
    })
    res.render('news/news_add.html', {
        cates
    })
})


// 图片上传

// 指定服务器中文件上传后的保存地址
const upload_dir = path.join(__dirname, '../public/uploads')

// 创建 multer 的实例对象，通过 dest 属性指定文件的存放路径
const upload = multer({
    dest: upload_dir
})

// upload.single() 是一个局部生效的中间件，用来解析 FormData 格式的表单数据
// 将文件类型的数据，解析并挂载到 req.file 属性中
// single函数的参数必须跟表单的文件的name属性保持一致

router.post('/upload', upload.single('file'), (req, res) => {
    //  获取上传好的文件数据对象
    const fileData = req.file

    // 允许上传的文件类型
    const allowMimeTypes = ['image/png', 'image/jpeg', 'image/gif', 'images/tmp']

    if (!allowMimeTypes.includes(fileData.mimetype)) {
        return res.cc(400, '必须上传图片格式的文件')
    }


    // 方式二：将图片转换为一个字符串（base64格式的字符串）
    const data = fs.readFileSync(fileData.path, 'binary')
    const buffer = new Buffer.from(data, 'binary');
    const str = buffer.toString('base64')
    const fileStr = `data:${fileData.mimetype};base64,` + str

    // 删除原始文件
    fs.unlinkSync(fileData.path)
    return res.cc(200, '上传成功', fileStr)


    // 方式一：返回图片在服务器的绝对路径
    /*  // 获取上传的文件后缀名
     const ext = fileData.mimetype.split('/')[1]
         // 获取文件上传的名字
     const filename = fileData.filename + '.' + ext
         // 读取文件的内容并且写入到文件中
         // 读取文件内容
     let img_str = fs.readFileSync(fileData.path)
         // 写文件
     fs.writeFileSync(path.join(fileData.destination, filename), img_str)
         // 删除原始文件
     fs.unlinkSync(fileData.path)
         // 最终返回的文件名必须是带有绝对路径的文件名，否则，无法被外部访问
     return res.cc(200, '上传成功', '/uploads/' + filename) */
})


// 新闻添加----接收表单数据
router.post('/news', expressJoi(news_add_schema), async(req, res) => {
    try {
        const body = req.body

        // 组装数据
        body.add_time = new Date()
            // 添加成功后返回添加成功的数据
        const result = await Article.create(body)
        if (result.id) {
            res.cc(200, 'ok', result.id)
        } else {
            res.cc(400, '添加失败')
        }

    } catch (e) {
        console.log(e.message)
    }

})

// 新闻列表----新闻列表页面展示
router.get('/news', async(req, res) => {
    // 获取所有的分类数据并传递到静态页面中
    const cates = await Cate.findAll({
        attributes: ['id', 'cate_name']
    })
    res.render('news/index.html', {
        cates
    })
})


// 新闻列表----新闻列表数据的API
router.get('/news/listApi', async(req, res) => {
    // 接收搜索条件

    const cate_id = req.query.cate_id - 0 || 0
    const title = req.query.title

    // 组装筛选条件
    let where = {
        is_del: 1
    }

    if (cate_id !== 0) {
        where.cate_id = cate_id
    }
    if (title !== '') {
        where.title = {
            // 模糊匹配
            [Op.like]: `%${title}%`
        }
    }

    // 先查询总记录数
    const data = await Article.findAll({
        attributes: ['id'],
        where
    })

    // 总记录数
    const total = data.length

    // 获取分页数据

    const page = req.query.page || 1
    const limit = req.query.limit || 3

    const result = await Article.findAll({
        attributes: ['id', 'title', 'author', 'add_time', 'picture'],
        where,
        include: [{
            model: Cate,
            attributes: ['cate_name']
        }],
        offset: (page - 1) * limit,
        limit: limit - 0
    })

    // 处理后台数据
    result && result.forEach((item, i) => {
        item.dataValues.index = i + 1
        item.dataValues.add_time = moment(item.dataValues.add_time).format('YYYY-MM-DD HH:mm:ss')
    })

    // 返回结果
    res.json({
        code: 0,
        msg: 'ok',
        count: total,
        data: result
    })
})

// 新闻删除---删除新闻的API
router.delete('/news/:id', async(req, res) => {
    try {
        // 接收id
        const id = req.params.id - 0

        // 查询id对应的数据
        const data = await Article.findAll({
            attributes: ['id', 'is_del'],
            where: {
                id
            }
        })
        if (data.length === 0) {
            return res.cc(400, '要删除数据不存在')
        }
        if (data[0].dataValues.is_del === -1) {
            return res.cc(200, 'ok')
        }

        // 软删除（更改数据表的is_del字段为-1）
        // 返回的受影响的行数
        const [num] = await Article.update({
            is_del: -1
        }, {
            where: {
                id
            }
        })
        if (num > 0) {
            return res.cc(200, 'ok')
        } else {
            return res.cc(400, '删除失败')
        }
    } catch (e) {
        console.log(e.message);
        return res.cc(500, e.message)
    }

})

// 新闻编辑---新闻编辑表单
router.get('/news/:id/edit', async(req, res) => {
    // 接收要编辑的新闻id
    const id = req.params.id

    // 查询出该新闻的数据

    const article = await Article.findOne({
        attributes: ['id', 'title', 'content', 'picture', 'author', 'cate_id'],
        where: {
            id
        }
    })

    // 查询出所有的分类数据
    const cates = await Cate.findAll({
        attributes: ['id', 'cate_name']
    })

    res.render('news/news_update.html', {
        cates,
        article
    })
})

// 新闻编辑---数据库修改
router.put('/news/:id', async(req, res) => {
    try {
        const id = req.params.id - 0
        const body = req.body

        // 组装数据
        body.add_time = new Date()
            // 添加成功后返回添加成功的数据
        const result = await Article.update(body, {
            where: {
                id
            }
        })
        if (result) {
            res.cc(200, 'ok')
        } else {
            res.cc(400, '修改失败')
        }

    } catch (e) {
        console.log(e.message)
    }

})

module.exports = router